package com.ozo.cloud.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ozo.cloud.common.base.model.BaseBatchDTO;
import com.ozo.cloud.common.base.model.BasePage;
import com.ozo.cloud.common.base.model.PageResult;
import com.ozo.cloud.common.core.exception.ServiceException;
import com.ozo.cloud.common.database.util.SortUtils;
import com.ozo.cloud.manage.entity.*;
import com.ozo.cloud.manage.exception.ManageExceptionEnum;
import com.ozo.cloud.manage.mapper.SysDeptMapper;
import com.ozo.cloud.manage.mapper.SysPostMapper;
import com.ozo.cloud.manage.pojo.dto.ChangeStatusDTO;
import com.ozo.cloud.manage.pojo.dto.SysPostQueryDTO;
import com.ozo.cloud.manage.pojo.dto.SysPostSaveDTO;
import com.ozo.cloud.api.manage.vo.SysPostVO;
import com.ozo.cloud.manage.service.ISysPostService;
import com.ozo.cloud.manage.service.ISysUserPostRelService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 岗位 服务实现类
 *
 * @author qiangesoft
 * @version 1.0
 * @date 2024-11-16 23:43:39
 */
@RequiredArgsConstructor
@Service
public class SysPostServiceImpl extends ServiceImpl<SysPostMapper, SysPost> implements ISysPostService {

    private final SysDeptMapper sysDeptMapper;

    private final ISysUserPostRelService sysUserPostRelService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(SysPostSaveDTO saveDTO) {
        // 参数校验
        this.checkParam(null, saveDTO.getDeptId(), saveDTO.getPostName());

        SysPost sysPost = BeanUtil.copyProperties(saveDTO, SysPost.class);
        baseMapper.insert(sysPost);
    }

    /**
     * 合法性校验
     *
     * @param id
     * @param deptId
     * @param postName
     */
    private void checkParam(Long id, Long deptId, String postName) {
        LambdaQueryWrapper<SysPost> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysPost::getDeptId, deptId)
                .eq(SysPost::getPostName, postName)
                .ne(Objects.nonNull(id), SysPost::getId, id);
        Long count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new ServiceException(ManageExceptionEnum.POST_NAME_EXISTS);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remove(BaseBatchDTO<Long> batchDTO) {
        baseMapper.deleteBatchIds(batchDTO.getIdList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SysPostSaveDTO saveDTO) {
        // 参数校验
        this.checkParam(saveDTO.getId(), saveDTO.getDeptId(), saveDTO.getPostName());

        SysPost sysPost = BeanUtil.copyProperties(saveDTO, SysPost.class);
        baseMapper.updateById(sysPost);
    }

    @Override
    public PageResult<SysPostVO> page(BasePage basePage, SysPostQueryDTO queryDTO) {
        Integer pageNum = basePage.getPageNum();
        Integer pageSize = basePage.getPageSize();

        QueryWrapper<SysPost> queryWrapper = new QueryWrapper<>();
        // 排序
        String order = basePage.getOrder();
        if (StrUtil.isBlank(order)) {
            queryWrapper.lambda().orderByAsc(SysPost::getOrderNum);
        } else {
            SortUtils.setSortCondition(queryWrapper, basePage.getProp(), order);
        }
        // 条件
        queryWrapper.lambda()
                .eq(Objects.nonNull(queryDTO.getDeptId()), SysPost::getDeptId, queryDTO.getDeptId())
                .like(StrUtil.isNotBlank(queryDTO.getPostName()), SysPost::getPostName, queryDTO.getPostName());
        Page<SysPost> page = baseMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);

        PageResult<SysPostVO> pageResult = new PageResult<>();
        pageResult.setPageNum(pageNum);
        pageResult.setPageSize(pageSize);
        pageResult.setPage(page.getPages());
        pageResult.setTotal(page.getTotal());
        List<SysPost> recordList = page.getRecords();
        List<SysPostVO> recordVOList = BeanUtil.copyToList(recordList, SysPostVO.class);
        pageResult.setResults(recordVOList);
        if (CollUtil.isEmpty(recordList)) {
            return pageResult;
        }

        Set<Long> deptIds = recordVOList.stream().filter(e -> Objects.nonNull(e.getDeptId())).map(SysPostVO::getDeptId).collect(Collectors.toSet());
        if (CollUtil.isNotEmpty(deptIds)) {
            Map<Long, String> deptMap = sysDeptMapper.selectBatchIds(deptIds).stream().collect(Collectors.toMap(SysDept::getId, SysDept::getDeptName));
            recordVOList.forEach(e -> e.setDeptName(deptMap.get(e.getDeptId())));
        }
        return pageResult;
    }

    @Override
    public void changeStatus(ChangeStatusDTO statusDTO) {
        LambdaUpdateWrapper<SysPost> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SysPost::getId, statusDTO.getId())
                .set(SysPost::getStatus, statusDTO.getStatus());
        baseMapper.update(updateWrapper);
    }

    @Override
    public Map<Long, List<SysPostVO>> listByUserIds(List<Long> userIdList) {
        List<SysUserPostRel> sysUserPostRelList = sysUserPostRelService.lambdaQuery().in(SysUserPostRel::getUserId, userIdList).list();
        Map<Long, List<SysUserPostRel>> groupPostMap = sysUserPostRelList.stream().collect(Collectors.groupingBy(SysUserPostRel::getUserId));
        Set<Long> postIdSet = sysUserPostRelList.stream().map(SysUserPostRel::getPostId).collect(Collectors.toSet());

        Map<Long, List<SysPostVO>> postMap = new HashMap<>();
        if (postIdSet.isEmpty()) {
            return postMap;
        }

        List<SysPost> sysPostList = baseMapper.selectBatchIds(postIdSet);
        List<SysPostVO> sysPostVOList = BeanUtil.copyToList(sysPostList, SysPostVO.class);

        for (Long userId : userIdList) {
            List<SysUserPostRel> postRelList = groupPostMap.get(userId);
            if (CollUtil.isNotEmpty(postRelList)) {
                Set<Long> postIds = postRelList.stream().map(SysUserPostRel::getPostId).collect(Collectors.toSet());
                List<SysPostVO> postVOList = sysPostVOList.stream().filter(e -> postIds.contains(e.getId())).collect(Collectors.toList());
                postMap.put(userId, postVOList);
            } else {
                postMap.put(userId, List.of());
            }
        }
        return postMap;
    }

    @Override
    public List<SysPostVO> list(SysPostQueryDTO queryDTO) {
        LambdaQueryWrapper<SysPost> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(SysPost::getOrderNum)
                .eq(Objects.nonNull(queryDTO.getDeptId()), SysPost::getDeptId, queryDTO.getDeptId())
                .like(StrUtil.isNotBlank(queryDTO.getPostName()), SysPost::getPostName, queryDTO.getPostName());
        List<SysPost> list = baseMapper.selectList(queryWrapper);
        return BeanUtil.copyToList(list, SysPostVO.class);
    }

}
